package com.sbl.utils;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * 和事务管理相关的工具类，它包含了，开启事务，提交事务，回滚事务和释放连接
 * 顺序：https://blog.csdn.net/rainbow702/article/details/52185827
 *      执行顺序问题：
 *          1. Before
 *          2. after
 *          3. after-return 或者after-throw
 *
 *  自定义的事务管理器，Anno
 *
 *
 */
@Component("txManager")
@Aspect
public class TransactionManagerMyByAnno {

    @Autowired
    private ConnectionUtilsAnno connectionUtils;

    @Pointcut("execution(* com.sbl.service.impl.*.*(..))")
    private void pt1(){}


    /**
     * 开启事务
     */
    @Before("pt1()")
    public  void beginTransaction(){
        System.out.println("Anno 开启事务");
        try {
            connectionUtils.getThreadConnection().setAutoCommit(false);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 提交事务
     */
    @AfterReturning("pt1()")
    public  void commit(){
        System.out.println("Anno 提交事务");
        try {
            connectionUtils.getThreadConnection().commit();
        }catch (Exception e){
            e.printStackTrace();
        }
    }



    /**
     * 回滚事务
     */
    @AfterThrowing("pt1()")
    public  void rollback(){
        System.out.println("Anno 回滚事务");
        try {
            connectionUtils.getThreadConnection().rollback();
        }catch (Exception e){
            e.printStackTrace();
        }
    }



    /**
     * 释放连接
     */
    @After("pt1()")
    public  void release(){
        System.out.println("Anno 释放事务");
        try {
            connectionUtils.getThreadConnection().close();//还回连接池中
            connectionUtils.removeConnection();
        }catch (Exception e){
            e.printStackTrace();
        }
    }




//    @Around("pt1()")
    public Object aroundAdvice(ProceedingJoinPoint pjp){
        Object rtValue = null;
        try {
            //1.获取参数
            Object[] args = pjp.getArgs();
            //2.开启事务
            this.beginTransaction();
            //3.执行方法
            rtValue = pjp.proceed(args);
            //4.提交事务
            this.commit();

            //返回结果
            return  rtValue;

        }catch (Throwable e){
            //5.回滚事务
            this.rollback();
            throw new RuntimeException(e);
        }finally {
            //6.释放资源
            this.release();
        }
    }
}
